/**
 * @brief  以下是使用C语言实现的双链表，其中链表结构体内嵌了一个数据域结构体。
 * @author SXSBJS_XYT
*/
#include <stdio.h>
#include <stdlib.h>


/**
 * struct Data 是一个数据域结构体，只包含一个value成员用于存储数据
 * struct Node 是一个链表结构体，它内嵌了一个struct Data，并且还包含了指向前一个节点和后一个节点的指针
*/
struct Node {
    struct Data {
        int value;
    } data;
    struct Node* prev;
    struct Node* next;
};
/**
 * @brief Create a Node object 
 *        创建一个新的节点并为其分配内存。然后将指定的值赋给节点的数据域，
 *        同时将节点的前一个节点和后一个节点的指针设置为NULL
 * 
 * @param value 
 * @return struct Node* 
 */
struct Node* createNode(int value) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    if (newNode == NULL) {
        printf("Memory allocation failed!\n");
        exit(1);
    }
    newNode->data.value = value;
    newNode->prev = NULL;
    newNode->next = NULL;
    return newNode;
}
/**
 * @brief insertAtBeginning函数用于在链表的开头插入一个新的节点。
 *        如果链表为空，则直接将新节点作为头节点。否则将新节点的next指针设置为原来的头节点，
 *        并将原来的头节点的prev指针设为新节点，最后将新节点设置为头节点。
 * 
 * @param head 
 * @param value 
 */
void insertAtBeginning(struct Node** head, int value) {
    struct Node* newNode = createNode(value);
    if (*head == NULL) {
        *head = newNode;
    } else {
        newNode->next = *head;
        (*head)->prev = newNode;
        *head = newNode;
    }
}
/**
 * @brief display函数用于遍历并显示双链表中的所有节点的值。
 *        它从头节点开始，依次打印每个节点的数据域的值，直到当前节点为空。
 * 
 * @param head 
 */
void display(struct Node* head) {
    struct Node* current = head;
    
    if (head == NULL) {
        printf("List is empty.\n");
        return;
    }
    
    printf("Nodes of the doubly linked list:\n");
    while (current != NULL) {
        printf("%d ", current->data.value);
        current = current->next;
    }
    printf("\n");
}
/**
 * @brief 在main函数中，创建一个空的双链表头节点，
 *        并通过调用insertAtBeginning函数插入了一些节点。
 *        最后，我们调用display函数来打印双链表中的节点值。
 * 
 * @return int 
 */
int main() {
    struct Node* head = NULL;
    
    insertAtBeginning(&head, 3);
    insertAtBeginning(&head, 2);
    insertAtBeginning(&head, 1);
    
    display(head);
    
    return 0;
}
